package com.sondon.dev_soceket.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelId;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.SSLException;

/**
 * @Project : Java_C_Socket_Maven
 * @Package : com.sondon.netty
 * @Class : DeviceTCPServer.java
 * @Company 广州讯动网络科技有限公司
 * @Author : 蔡文锋
 * @DateTime：2015年4月22日 下午5:52:18
 * @Blog：http://blog.csdn.net/caiwenfeng_for_23
 * @Description : {Neety启动类}
 */
public final class DeviceTCPServer {
	static final boolean SSL = System.getProperty("ssl") != null;
	static final int PORT = Integer.parseInt(System.getProperty("port", "8322"));
	 //ChannelGroup 保存channel
	public static final ChannelGroup channel_group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
	public static final Map<String,ChannelId> channel_map=new HashMap<String, ChannelId>();
	public static final ServerBootstrap serverbootstap = new ServerBootstrap();
	
	/**
	 * @throws CertificateException
	 * @throws SSLException
	 * @throws InterruptedException
	 * @Author 蔡文锋
	 * @Data_Time 2015年4月24日 上午11:12:26
	 * @Description {启动DevSocket}
	 */
	public static void StartDevSocket() {
		try {
			// Configure SSL.
			final SslContext sslCtx;
			if (SSL) {
				SelfSignedCertificate ssc = new SelfSignedCertificate();
				sslCtx = SslContext.newServerContext(ssc.certificate(),
						ssc.privateKey());
			} else {
				sslCtx = null;
			}

			EventLoopGroup bossGroup = new NioEventLoopGroup(1);
			EventLoopGroup workerGroup = new NioEventLoopGroup();

			try {
		
				/*
				 * Netty5中ByteBuf对象的创建方式对内存的影响
				 * http://xiaochu.blog.51cto.com/1048262/1588426
				 */
				serverbootstap
						.group(bossGroup, workerGroup)
						.channel(NioServerSocketChannel.class)
						.childHandler(new DeviceTCPServerInitializer(sslCtx))
						.option(ChannelOption.SO_BACKLOG, 1024)
						.option(ChannelOption.SO_RCVBUF, 1024 * 256)
						.option(ChannelOption.SO_SNDBUF, 1024 * 256)
						.option(ChannelOption.ALLOCATOR,PooledByteBufAllocator.DEFAULT)
						.option(ChannelOption.SO_REUSEADDR, true)
						.childOption(ChannelOption.ALLOCATOR,PooledByteBufAllocator.DEFAULT)
						.childOption(ChannelOption.SO_KEEPALIVE, true);

				//绑定端口 等待绑定成功
		        ChannelFuture future=serverbootstap.bind(PORT).sync();
		        //等待服务器退出
		        future.channel().closeFuture().sync().addListener(new GenericFutureListener<Future<? super Void>>() {

					@Override
					public void operationComplete(Future<? super Void> future)
							throws Exception {
						// TODO Auto-generated method stub
						System.out.println("服务器已经退出....");
					}
				});
		        
		        }finally{
		            //释放线程资源
		            bossGroup.shutdownGracefully();
		            workerGroup.shutdownGracefully();
		        }
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	
	/**
	* @Author 蔡文锋
	* @Data_Time 2015年4月25日  上午2:05:19
	* @Description {}
	 */
	public static void StopDevSocket(){
		System.out.println("stop devsocket ....");
		channel_group.close().awaitUninterruptibly();
		channel_group.clear();
	}
	
	public static void main(String[] args) {
		StartDevSocket();
	}
}
